#include"list.h"


struct List * createList(void *(*_createData)(const void *),
						 int (*_deleteData)(const void *),
						 int (*_duplicateNode)(Link, Link),
						 int (*_dataCmp)(const void* data1,const void* data2),
						 void (*_printInfo)())
{
	struct List * _plist = (struct List *)(calloc(sizeof(struct List),1));
	if(_plist==NULL)
		return NULL;
	_plist->_createData = _createData;
	_plist->_deleteData = _deleteData;
	_plist->_duplicateNode = _duplicateNode;
	_plist->_dataCmp = _dataCmp;
	_plist->_printInfo = _printInfo;

	return _plist;
}

int addNodeAtHead(struct List* _plist, void* data)
{
	Link _newNode = createNode(_plist, data);
	if(_newNode==NULL)
		return 0;

	if(_plist->_head==NULL)	//the list is empty
	{
		_newNode->prev = _newNode->next = NULL;
		_plist->_tail = _plist->_head = _newNode;
	}
	else
	{
		_newNode->next = _plist->_head;
		_plist->_head->prev = _newNode;
		_plist->_head = _newNode;
	}

	_plist->count++;
	return 1;
}

Link createNode(struct List* _plist, void* data)
{
	Link _newNode = (Link)calloc(sizeof(struct Node), 1);
	if(_newNode==NULL)
		return NULL;

	_newNode->p_data = _plist->_createData(data);
	if(_newNode->p_data==NULL)
	{
		free(_newNode);
		return NULL;
	}

	return _newNode;
}

int deleteNode(struct List* _plist, Link to_delete)
{
	if(to_delete==NULL)
		return 0;

	if(to_delete->prev==NULL&&to_delete->next==NULL)
	{
		_plist->_head = _plist->_tail = NULL;
	}
	else if(to_delete->prev==NULL)
	{
		_plist->_head = to_delete->next;
		_plist->_head->prev = NULL;
	}
	else if(to_delete->next==NULL)
	{
		_plist->_tail = to_delete->prev;
		_plist->_tail->next = NULL;
	}
	else
	{
		to_delete->prev->next = to_delete->next;
		to_delete->next->prev = to_delete->prev;
	}
	
	_plist->_deleteData(to_delete->p_data);
	free(to_delete);
	_plist->count--;
	return 1;
}

Link findNode(struct List* _plist, void* data)
{
	if(data==NULL)
		return NULL;

	Link pn = _plist->_head;
	while(pn!=NULL)
	{
		if(_plist->_dataCmp(pn->p_data, data)==0)
			return pn;

		pn = pn->next;
	}

	return NULL;
}

void printInfo(struct List* _plist)
{
	if(_plist==NULL)
		return;
	Link pn = _plist->_head;

	while(pn!=NULL)
	{
		_plist->_printInfo(pn->p_data);
		pn = pn->next;
	}
	return;
}


int deleteList(struct List* _plist)
{
	Link pn = _plist->_head;
	while(pn!=NULL)
	{
		deleteNode(_plist, pn);
		pn = _plist->_head;
	}
	return 1;
}
